import {Matrix} from "@/components/comm/matrix";
import {HexContainer, HexPosition} from "@/components/hex/HexContainer";
import {Position} from "@/components/comm/utils";

export class HexGraph<T> extends HexContainer<T> {
    public constructor(readonly side: number, fn: (pos: HexPosition) => T) {
        super();
        this.data = Matrix.from(2 * side + 1, 2 * side + 1, () => undefined);
        for (const pos of this.indexes()) {
            this.set(pos, fn(pos));
        }
    }

    private cubeToAxial([x, _, z]: HexPosition): [number, number] {
        return [x + this.side, z + this.side];
    }

    private axialToCube([q, r]: Position): HexPosition {
        return [q - this.side, -q - r + 2 * this.side, r - this.side];
    }

    protected cubeToIndex(pos: HexPosition): [number, number] {
        return this.cubeToAxial(pos);
    }

    protected indexToCube(index: Position): HexPosition {
        return this.axialToCube(index);
    }

    public contains(pos: HexPosition): boolean {
        const [x, y, z] = pos;
        return -this.side <= x && x <= this.side &&
            -this.side <= y && y <= this.side &&
            -this.side <= z && z <= this.side &&
            x + y + z === 0;
    }

    public indexes(): Generator<HexPosition> {
        return this.spiralIter([0, 0, 0], 0, this.side);
    }
}